package tr.edu.metu.is.mega.client.user;

import java.util.ArrayList;
import java.util.List;

import tr.edu.metu.is.mega.client.core.DialogCallback;
import tr.edu.metu.is.mega.client.resource.MEGAIconBundle;
import tr.edu.metu.is.mega.client.resource.MEGAResourceBundle;
import tr.edu.metu.is.mega.client.resource.MEGAResources;
import tr.edu.metu.is.mega.client.widgets.MegaCompositeWidget;
import tr.edu.metu.is.mega.common.dto.UserDTO;
import tr.edu.metu.is.mega.common.dto.UserRole;

import com.extjs.gxt.ui.client.event.ButtonEvent;
import com.extjs.gxt.ui.client.event.SelectionListener;
import com.extjs.gxt.ui.client.util.Margins;
import com.extjs.gxt.ui.client.widget.LayoutContainer;
import com.extjs.gxt.ui.client.widget.button.Button;
import com.extjs.gxt.ui.client.widget.form.TextField;
import com.extjs.gxt.ui.client.widget.layout.HBoxLayout;
import com.extjs.gxt.ui.client.widget.layout.HBoxLayout.HBoxLayoutAlign;
import com.extjs.gxt.ui.client.widget.layout.HBoxLayoutData;
import com.google.gwt.user.client.Element;
import com.google.gwt.user.client.ui.AbstractImagePrototype;

/**
 * User selection widget.
 * 
 */
public class UserWidget extends LayoutContainer implements MegaCompositeWidget {

    private List<UserDTO> selectedUserList;

    private TextField<String> txtUserDesc;

    private final MEGAIconBundle iconBundle = MEGAResources.ICONBUNDLE;

    private final MEGAResourceBundle resourceBundle = MEGAResources.RESOURCEBUNDLE;

    private final UserSelectDialog userSelectDialog;

    private final boolean multiSelect;

    /**
     * Default constructor.
     * 
     * @param enablePersonEdit true to enable person edit
     */
    public UserWidget(boolean multiSelect, boolean enablePersonEdit) {
        this(multiSelect, enablePersonEdit, null);
    }

    /**
     * Default constructor.
     * 
     * @param enablePersonEdit true to enable person edit
     * @param userRole user type to be displayed.
     */
    public UserWidget(boolean multiSelect, boolean enablePersonEdit, UserRole userRole) {
        this.multiSelect = multiSelect;
        userSelectDialog = new UserSelectDialog(multiSelect, enablePersonEdit, userRole);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    protected void onRender(Element parent, int index) {
        super.onRender(parent, index);

        HBoxLayout hBoxLayout = new HBoxLayout();
        hBoxLayout.setHBoxLayoutAlign(HBoxLayoutAlign.TOP);
        setLayout(hBoxLayout);

        txtUserDesc = new TextField<String>();
        txtUserDesc.setReadOnly(true);

        Button buttonSelect = new Button();
        buttonSelect.setIcon(AbstractImagePrototype.create(iconBundle.search()));
        buttonSelect.setToolTip(resourceBundle.select());
        buttonSelect.addSelectionListener(new SelectionListener<ButtonEvent>() {

            @Override
            public void componentSelected(ButtonEvent ce) {
                userSelectDialog.select(new DialogCallback<UserDTO>() {

                    @Override
                    public void onOk(UserDTO param) {
                        setValue(param);
                    }

                    @Override
                    public void onOk(List<UserDTO> params) {
                        setValueList(params);
                    }

                    @Override
                    public void onCancel() {
                    }
                });
            }
        });

        Button buttonClear = new Button();
        buttonClear.setIcon(AbstractImagePrototype.create(iconBundle.clear()));
        buttonClear.setToolTip(resourceBundle.delete());
        buttonClear.addSelectionListener(new SelectionListener<ButtonEvent>() {

            @Override
            public void componentSelected(ButtonEvent ce) {
                setValue(null);
            }
        });

        add(txtUserDesc, new HBoxLayoutData(new Margins(0, 2, 0, 0)));
        add(buttonSelect, new HBoxLayoutData(new Margins(0, 2, 0, 0)));
        add(buttonClear, new HBoxLayoutData(new Margins(0)));
    }

    /**
     * Sets selected person.
     * 
     * @param selectedUser the person to set
     */
    public void setValue(UserDTO selectedUser) {
        this.selectedUserList = new ArrayList<UserDTO>();
        selectedUserList.add(selectedUser);
        if (selectedUser == null) {
            txtUserDesc.setValue(null);
        } else {
            txtUserDesc.setValue(selectedUser.getFullName());
        }
    }

    /**
     * Sets selected person list.
     * 
     * @param selectedUserList person list to set
     */
    public void setValueList(List<UserDTO> selectedUserList) {
        this.selectedUserList = selectedUserList;
        if (selectedUserList == null) {
            txtUserDesc.setValue(null);
        } else {
            String value = "";
            for (UserDTO dto : selectedUserList) {
                value += dto.getFullName() + ", ";
            }
            txtUserDesc.setValue(value.substring(0, value.length() - 2));
        }
    }

    /**
     * @return selected user list
     */
    public List<UserDTO> getValue() {
        return selectedUserList;
    }

    /**
     * @return selected user
     */
    public UserDTO getSingleValue() {
        return selectedUserList.get(0);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public Object getWidgetValue() {
        if (multiSelect) {
            return getValue();
        } else {
            return getSingleValue();
        }
    }

    /**
     * {@inheritDoc}
     */
    @SuppressWarnings("unchecked")
    @Override
    public void setWidgetValue(Object value) {
        if (value instanceof UserDTO) {
            setValue((UserDTO) value);
        } else {
            try {
                setValueList((List<UserDTO>) value);
            } catch (Exception e) {
                throw new IllegalArgumentException("Parameter is not UserDTO");
            }
        }

    }

}
